/**
 * Copyright 2016 JustWayward Team
 * <p/>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p/>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p/>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.taptech.doufu.ui.view.readview;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Picture;
import android.graphics.Rect;
import android.graphics.drawable.PictureDrawable;
import androidx.core.content.ContextCompat;
import android.text.TextUtils;
import android.util.SparseArray;

import com.taptech.doufu.util.DensityUtil;
import com.taptech.doufu.R;
import com.taptech.doufu.app.WeMediaApplication;
import com.taptech.doufu.ui.view.readview.util.FileUtils;
import com.taptech.doufu.ui.view.readview.util.ScreenUtils;
import com.taptech.doufu.ui.view.theme.read.ReadTheme;
import com.taptech.doufu.ui.view.theme.read.ReadThemeHelper;
import com.taptech.doufu.util.MobileState;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;


public class PageFactory {
    private static int TITLE_MARGIN_BUTTOM = 40;
    private static float PART_SPACE_MULTIPLE = 1.0f;
    /**
     * 屏幕宽高
     */
    private int mHeight, mWidth;
    /**
     * 文字区域宽高
     */
    private int mVisibleHeight, mVisibleWidth;
    /**
     * 间距
     */
    private int marginWidth;

    private int statusBarMarginLeft,statusBarMarginTop,contentMarginBottom,contentMarginTop;

    /**
     * 字体大小
     */
    private int mFontSize, mStatusBarSize,mTitleSize;
    /**
     * 每页行数
     */
    private int mPageLineCount;
    /**
     * 行间距
     **/
    private int mLineSpace;
    private float mLineMultiple; //行间距 字体倍数

    /**
     * 段间距
     */
    private int mPartSpace;

    private MobileState mobileState;

    /**
     * 字节长度
     */
    private int mbBufferLen;
    /**
     * MappedByteBuffer：高效的文件内存映射
     */
    private MappedByteBuffer mbBuff;

    /**
     * 页首页尾的位置
     */
    private int curEndPos = 0, curBeginPos = 0, tempBeginPos;
    private int tempcurrPage;
    private int currentChapter;

    public int getCurrentChapter() {
        return currentChapter;
    }

    public int getCurEndPos() {
        return curEndPos;
    }

    public int getCurBeginPos() {
        return curBeginPos;
    }

    private int tempChapter;
    private Vector<String> mLines = new Vector<>();

    private Paint mPaint;
    private Paint mTitlePaint;
    private Paint mStatusBarPaint;
    private Paint mBottomStatusPaint;
    private Picture mPicture,prePicture;
    private PictureDrawable mDrawable,preDrawable;
    private Paint mLinePaint;
    private Paint mProgressPaint;
    private String bookId;
    private SparseArray<String> chaptersList;
    private Context mContext;
    private int currChapterPageNum;

    public void setCurrentPage(int currentPage) {
        this.currentPage = currentPage;
    }

    private int currentPage = 1;

    private OnReadStateChangeListener listener;
    private String charset = "UTF-8";

    public void setChaptersList(SparseArray<String> array) {
        chaptersList = array;
    }

    public PageFactory(Context context, String bookId, MobileState mobileState,int fontSize,float lineSpace, SparseArray<String> chaptersList) {
        this(context, ScreenUtils.getScreenWidth(), ScreenUtils.getScreenHeight(),mobileState,
                fontSize,lineSpace,
                bookId, chaptersList);
    }

    public PageFactory(Context context, int width, int height,MobileState mobileState, int fontSize,float lineMultiple, String bookId,
                       SparseArray<String> chaptersList) {
        mLineMultiple =lineMultiple;
        mContext = context;
        mWidth = width;
        mHeight = height;
        mFontSize = fontSize;
        mLineSpace = (int) (mLineMultiple*mFontSize);
        mPartSpace = (int) (PART_SPACE_MULTIPLE * mFontSize);
        mTitleSize = getTitleFontSize(fontSize);
        mStatusBarSize = DensityUtil.sp2px(context, 10);
        statusBarMarginLeft = DensityUtil.dip2px(context, 15);
        statusBarMarginTop = DensityUtil.dip2px(context,12);
        contentMarginBottom = DensityUtil.dip2px(context, 60);
        contentMarginTop = DensityUtil.dip2px(context, 65);
        marginWidth = ScreenUtils.dpToPxInt(24);
        mVisibleHeight = mHeight - contentMarginTop - contentMarginBottom;
        mVisibleWidth = mWidth - marginWidth * 2;
        setmPageLineCount();
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setTextSize(mFontSize);
        mPaint.setTextSize(ContextCompat.getColor(context, R.color.chapter_content_day));
        mPaint.setColor(Color.BLACK);
        mTitlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTitlePaint.setColor(ContextCompat.getColor(context, R.color.chapter_title_day));
        mTitlePaint.setTextSize(mTitleSize);
        mStatusBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mStatusBarPaint.setColor(ContextCompat.getColor(context, R.color.read_desc_font_color_day));
        mStatusBarPaint.setTextSize(mStatusBarSize);
        mBottomStatusPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBottomStatusPaint.setColor(ContextCompat.getColor(context, R.color.read_desc_font_color_day));
        mBottomStatusPaint.setTextSize(DensityUtil.dip2px(context,11));
        mProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPicture = new Picture();
        prePicture = new Picture();
        mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mLinePaint.setColor(ContextCompat.getColor(context, R.color.chapter_title_day));
        this.bookId = bookId;
        this.chaptersList = chaptersList;
        setReadTheme(ReadThemeHelper.getReadTheme());
        this.mobileState = mobileState;
    }

    public File getBookFile(int chapter) {
        File file = FileUtils.getChapterFile(bookId, chapter);
//        charset = FileUtils.getCharset(file.getAbsolutePath());
        return file;
    }


    /**
     * 打开书籍文件
     *
     * @param chapter  阅读章节
     * @param position 阅读位置
     * @param isCalcuationPage 是否要计算章节的页数
     * @return 0：文件不存在或打开失败  1：打开成功
     */
    public int openBook(int chapter, int[] position,boolean isCalcuationPage) {
        this.currentChapter = chapter;
        String path = getBookFile(currentChapter).getPath();
        try {
            File file = new File(path);
            if (file.exists()) {
                long length = file.length();
                if (length > 10) {
                    mbBufferLen = (int) length;
                    // 创建文件通道，映射为MappedByteBuffer
                    mbBuff = new RandomAccessFile(file, "r")
                            .getChannel()
                            .map(FileChannel.MapMode.READ_ONLY, 0, length);
                    curBeginPos = position[0];
                    curEndPos = position[1];
                    if (isCalcuationPage) {
                        getPageNum(chapter);
                    }
                    onChapterChanged(chapter);
                    mLines.clear();
                    return 1;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return 0;
    }

    private synchronized List<String> getTitleLine(String title) {
        List<String> lines = new ArrayList<>();
        while (title.length() > 0) {
            int paintSize = mTitlePaint.breakText(title, true, mVisibleWidth, null);
            if (paintSize > title.length()) {
                paintSize = title.length();
            }
            lines.add(title.substring(0, paintSize));
            title = title.substring(paintSize);
        }
        return lines;
    }


    /**
     * 记录上一页
     */
    public synchronized void setPrePicture() {
        Canvas canvas = prePicture.beginRecording(ScreenUtils.getScreenWidth(),ScreenUtils.getScreenHeight());
        onDrawView(canvas);
        prePicture.endRecording();
        preDrawable = new PictureDrawable(prePicture);
    }

    /**
     * 用于自动阅读
     */
    public synchronized void setPicture() {
        Canvas canvas = mPicture.beginRecording(ScreenUtils.getScreenWidth(),ScreenUtils.getScreenHeight());
        onDrawView(canvas);
        mPicture.endRecording();
        mDrawable = new PictureDrawable(mPicture);
    }

    public synchronized void onDrawProgress(Canvas canvas, int right) {
        canvas.drawRect(0,0,right,8,mProgressPaint);
    }

    public synchronized void onDrawPlay(Canvas canvas,int bottom) {
        if (mDrawable == null) {
            if (mPicture != null) {
                mDrawable = new PictureDrawable(mPicture);
            }else{
                return;
            }
        }
        mDrawable.setBounds(0,0,ScreenUtils.getScreenWidth(),bottom);
        mDrawable.draw(canvas);
        canvas.drawLine(0,bottom,ScreenUtils.getScreenWidth(),bottom, mLinePaint);
    }


    public synchronized void onDrawPre(Canvas canvas) {
        if (preDrawable != null) {
            preDrawable.setBounds(0,0,ScreenUtils.getScreenWidth(),ScreenUtils.getScreenHeight());
            preDrawable.draw(canvas);
        }
    }

    /**
     * 绘制阅读页面
     *
     * @param canvas
     */
    public synchronized void onDraw(Canvas canvas) {
        onDrawView(canvas);
    }

    private void onDrawView(Canvas canvas) {
        if (mLines.size() == 0) {
            curEndPos = curBeginPos;
            mLines = pageDown();
        }
        if (mLines.size() > 0) {
            int y = contentMarginTop;
            // 绘制背景
            if (ReadThemeHelper.bgIsPicture(ReadThemeHelper.getReadTheme())) {
                drawImage(canvas, BitmapFactory.decodeResource(mContext.getResources(), ReadThemeHelper.getReadTheme().getContentBg()),
                        0, 0, ScreenUtils.getScreenWidth(),ScreenUtils.getScreenHeight(),0, 0);
            }else{
                canvas.drawColor(mContext.getResources().getColor(ReadThemeHelper.getReadTheme().getContentBg()));
            }
            canvas.drawText(getTopLeftString(), statusBarMarginLeft, mStatusBarSize+statusBarMarginTop, mStatusBarPaint);
            mBottomStatusPaint.setTextAlign(Paint.Align.RIGHT);
            canvas.drawText(getBottomRightString(), ScreenUtils.getScreenWidth()- DensityUtil.dip2px(mContext,25),
                    ScreenUtils.getScreenHeight()-DensityUtil.dip2px(mContext,18),
                    mBottomStatusPaint);
            mBottomStatusPaint.setTextAlign(Paint.Align.LEFT);
            drawImage(canvas, BitmapFactory.decodeResource(mContext.getResources(), MobileState.getBatteryResource(mobileState)), statusBarMarginLeft, ScreenUtils.getScreenHeight() - DensityUtil.dip2px(mContext, 27),
                    DensityUtil.dip2px(mContext,16),DensityUtil.dip2px(mContext,9),0, 0);
            if(mobileState.isCharger){
                drawImage(canvas, BitmapFactory.decodeResource(mContext.getResources(), ReadThemeHelper.getReadTheme().getBatteryTheme().getBatteryAdd()),
                        statusBarMarginLeft+DensityUtil.dip2px(mContext,19), ScreenUtils.getScreenHeight() - DensityUtil.dip2px(mContext, 27),
                        DensityUtil.dip2px(mContext,9),DensityUtil.dip2px(mContext,9),0, 0);
                canvas.drawText(getTime(),statusBarMarginLeft+DensityUtil.dip2px(mContext,36),
                        ScreenUtils.getScreenHeight()-DensityUtil.dip2px(mContext,18),mBottomStatusPaint);
            }else{
                canvas.drawText(getTime(),statusBarMarginLeft+DensityUtil.dip2px(mContext,26),
                        ScreenUtils.getScreenHeight()-DensityUtil.dip2px(mContext,18),mBottomStatusPaint);
            }
            if (curBeginPos==0&& !TextUtils.isEmpty(title)) {
                List<String> lines = getTitleLine(title);
                y+=mTitleSize;
                for (int i = 0; i < lines.size(); i++) {
                    String line = lines.get(i);
                    canvas.drawText(line, marginWidth, y, mTitlePaint);
                    y += mTitleSize+mLineSpace;
                }
                y+=TITLE_MARGIN_BUTTOM;
            }
            // 绘制阅读页面文字
            for (String line : mLines) {
                y += mLineSpace;
                if (line.endsWith("@")) {
                    canvas.drawText(line.substring(0, line.length() - 1), marginWidth, y, mPaint);
                    y += mPartSpace;
                } else {
                    canvas.drawText(line, marginWidth, y, mPaint);
                }
                y += mFontSize;
            }
        }
    }

    /*---------------------------------
     * 绘制图片
     * @param       x屏幕上的x坐标
     * @param       y屏幕上的y坐标
     * @param       w要绘制的图片的宽度
     * @param       h要绘制的图片的高度
     * @param       bx图片上的x坐标
     * @param       by图片上的y坐标
     *
     * @return      null
     ------------------------------------*/

    public static void drawImage(Canvas canvas, Bitmap blt, int x, int y,
                                 int w, int h, int bx, int by) {
        Rect src = new Rect();// 图片 >>原矩形
        Rect dst = new Rect();// 屏幕 >>目标矩形

        src.left = bx;
        src.top = by;
        src.right = bx + w;
        src.bottom = by + h;

        dst.left = x;
        dst.top = y;
        dst.right = x + w;
        dst.bottom = y + h;
        // 画出指定的位图，位图将自动--》缩放/自动转换，以填补目标矩形
        // 这个方法的意思就像 将一个位图按照需求重画一遍，画后的位图就是我们需要的了
        canvas.drawBitmap(blt, null, dst, null);
        src = null;
        dst = null;
    }

    /**
     * 指针移到上一页页首
     */
    private void pageUp() {
        String strParagraph = "";
        Vector<String> lines = new Vector<>(); // 页面行
        int paraSpace = 0;
        setmPageLineCount();
        while ((lines.size() < mPageLineCount) && (curBeginPos > 0)) {
            Vector<String> paraLines = new Vector<>(); // 段落行
            byte[] parabuffer = readParagraphBack(curBeginPos); // 1.读取上一个段落

            curBeginPos -= parabuffer.length; // 2.变换起始位置指针
            try {
                strParagraph = new String(parabuffer, charset);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            strParagraph = strParagraph.replaceAll("\r\n", "  ");
            strParagraph = strParagraph.replaceAll("\n", " ");

            while (strParagraph.length() > 0) { // 3.逐行添加到lines
                int paintSize = mPaint.breakText(strParagraph, true, mVisibleWidth, null);
                if(paintSize>strParagraph.length()){
                    paintSize = strParagraph.length();
                }
                paraLines.add(strParagraph.substring(0, paintSize));
                strParagraph = strParagraph.substring(paintSize);
            }
            lines.addAll(0, paraLines);

            while (lines.size() > mPageLineCount) { // 4.如果段落添加完，但是超出一页，则超出部分需删减
                try {
                    curBeginPos += lines.get(0).getBytes(charset).length; // 5.删减行数同时起始位置指针也要跟着偏移
                    lines.remove(0);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
            curEndPos = curBeginPos; // 6.最后结束指针指向下一段的开始处
            paraSpace += mPartSpace;
            setmPageLineCount(paraSpace);
        }
    }


    private void setmPageLineCount(int paraSpace) {
        if (curBeginPos==0&&!TextUtils.isEmpty(title)) {
            List<String> lines = getTitleLine(title);
            mPageLineCount = (mVisibleHeight - paraSpace-(1+lines.size())*(mTitleSize)-lines.size()*mLineSpace) / (mFontSize + mLineSpace);
        } else {
            mPageLineCount = (mVisibleHeight - paraSpace) / (mFontSize + mLineSpace);// 添加段落间距，实时更新容纳行数
        }
    }

    private void setmPageLineCount() {
        if (curBeginPos==0&&!TextUtils.isEmpty(title)) {  //第一页需要空出标题的位置
            List<String> lines = getTitleLine(title);
            mPageLineCount = (mVisibleHeight-(1+lines.size())*(mTitleSize)-lines.size()*mLineSpace) / (mFontSize + 2*mLineSpace);
        } else {
            mPageLineCount = mVisibleHeight / (mFontSize + mLineSpace);
        }
    }

    /**
     * 根据起始位置指针，读取一页内容
     *
     * @return
     */
    private Vector<String> pageDown() {
        String strParagraph = "";
        Vector<String> lines = new Vector<>();
        int paraSpace = 0;
        setmPageLineCount();
        while ((lines.size() < mPageLineCount) && (curEndPos < mbBufferLen)) {
            byte[] parabuffer = readParagraphForward(curEndPos);
            curEndPos += parabuffer.length;
            try {
                strParagraph = new String(parabuffer, charset);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            strParagraph = strParagraph.replaceAll("\r\n", "  ")
                    .replaceAll("\n", " "); // 段落中的换行符去掉，绘制的时候再换行

            while (strParagraph.length() > 0) {
                int paintSize = mPaint.breakText(strParagraph, true, mVisibleWidth, null);
                if(paintSize>strParagraph.length()){
                    paintSize = strParagraph.length();
                }
                lines.add(strParagraph.substring(0, paintSize));
                strParagraph = strParagraph.substring(paintSize);
                if (lines.size() >= mPageLineCount) {
                    break;
                }
            }
            lines.set(lines.size() - 1, lines.get(lines.size() - 1) + "@");
            if (strParagraph.length() != 0) {
                try {
                    curEndPos -= (strParagraph).getBytes(charset).length;
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
            paraSpace += mPartSpace;
            setmPageLineCount(paraSpace);
        }
        return lines;
    }

    private Map<Integer, Integer> capterPageNum = new HashMap<>();

    public void clearPageAllCache() {
        capterPageNum.clear();
    }

    public void removePageCache(int capter) {
        if (capterPageNum.containsKey(Integer.valueOf(capter))) {
            capterPageNum.remove(Integer.valueOf(capter));
        }
    }

    private int tempPageLineCount,tempCurEndPos,tempCurBeginPos;
    private int allPageForChapter;
    public void getPageNum(int chapter) {
        if (capterPageNum.containsKey(Integer.valueOf(chapter))) {
            currChapterPageNum =capterPageNum.get(Integer.valueOf(chapter));
            listener.onPageNum(currChapterPageNum);
            onPageChanged(currentChapter,currentPage);
        } else {
            tempPageLineCount = mPageLineCount;
            tempCurBeginPos = curBeginPos;
            tempCurEndPos = curEndPos;
            allPageForChapter = 0;
            String strParagraph = "";
            Vector<String> lines = new Vector<>();
            curEndPos=0;
            while (curEndPos < mbBufferLen) {
                int paraSpace = 0;
                setmPageLineCount();
                curBeginPos = curEndPos;
                while ((lines.size() < mPageLineCount) && (curEndPos < mbBufferLen)) {
                    byte[] parabuffer = readParagraphForward(curEndPos);
                    curEndPos += parabuffer.length;
                    try {
                        strParagraph = new String(parabuffer, charset);
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                    strParagraph = strParagraph.replaceAll("\r\n", "  ");
                    strParagraph = strParagraph.replaceAll("\n", " "); // 段落中的换行符去掉，绘制的时候再换行
                    while (strParagraph.length() > 0) {
                        int paintSize = mPaint.breakText(strParagraph, true, mVisibleWidth, null);
                        if (paintSize > strParagraph.length()) {
                            paintSize = strParagraph.length();
                        }
                        lines.add(strParagraph.substring(0, paintSize));
                        strParagraph = strParagraph.substring(paintSize);
                        if (lines.size() >= mPageLineCount) {
                            break;
                        }
                    }
                    lines.set(lines.size() - 1, lines.get(lines.size() - 1) + "@");
                    if (strParagraph.length() != 0) {
                        try {
                            curEndPos -= (strParagraph).getBytes(charset).length;
                        } catch (UnsupportedEncodingException e) {
                            e.printStackTrace();
                        }
                    }
                    paraSpace += mPartSpace;
                    setmPageLineCount(paraSpace);
                }
                lines.clear();
                allPageForChapter++;
            }
            mPageLineCount = tempPageLineCount;
            curBeginPos = tempCurBeginPos;
            curEndPos = tempCurEndPos;
            capterPageNum.put(Integer.valueOf(chapter), Integer.valueOf(allPageForChapter));
            //回调
            currChapterPageNum = allPageForChapter;
            listener.onPageNum(allPageForChapter);
            onPageChanged(currentChapter,currentPage);
        }
    }

    /**
     * 获取最后一页的内容。比较繁琐，待优化
     *
     * @return
     */
    public Vector<String> pageLast() {
        String strParagraph = "";
        Vector<String> lines = new Vector<>();
        currentPage = 0;
        while (curEndPos < mbBufferLen) {
            int paraSpace = 0;
            setmPageLineCount();
            curBeginPos = curEndPos;
            while ((lines.size() < mPageLineCount) && (curEndPos < mbBufferLen)) {
                byte[] parabuffer = readParagraphForward(curEndPos);
                curEndPos += parabuffer.length;
                try {
                    strParagraph = new String(parabuffer, charset);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                strParagraph = strParagraph.replaceAll("\r\n", "  ");
                strParagraph = strParagraph.replaceAll("\n", " "); // 段落中的换行符去掉，绘制的时候再换行

                while (strParagraph.length() > 0) {
                    int paintSize = mPaint.breakText(strParagraph, true, mVisibleWidth, null);
                    if (paintSize > strParagraph.length()) {
                        paintSize = strParagraph.length();
                    }
                    lines.add(strParagraph.substring(0, paintSize));
                    strParagraph = strParagraph.substring(paintSize);
                    if (lines.size() >= mPageLineCount) {
                        break;
                    }
                }
                lines.set(lines.size() - 1, lines.get(lines.size() - 1) + "@");

                if (strParagraph.length() != 0) {
                    try {
                        curEndPos -= (strParagraph).getBytes(charset).length;
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                }
                paraSpace += mPartSpace;
                setmPageLineCount(paraSpace);
            }
            if (curEndPos < mbBufferLen) {
                lines.clear();
            }
            currentPage++;
        }
        currChapterPageNum = currentPage;
        listener.onPageNum(currentPage);
        capterPageNum.put(Integer.valueOf(currentChapter), Integer.valueOf(currentPage));
        return lines;
    }

    /**
     * 读取下一段落
     *
     * @param curEndPos 当前页结束位置指针
     * @return
     */
    private byte[] readParagraphForward(int curEndPos) {
        try {
            byte b0;
            int i = curEndPos;
            while (i < mbBufferLen) {
                b0 = mbBuff.get(i++);
                if (b0 == 0x0a) {
                    break;
                }
            }
            int nParaSize = i - curEndPos;
            byte[] buf = new byte[nParaSize];
            for (i = 0; i < nParaSize; i++) {
                buf[i] = mbBuff.get(curEndPos + i);
            }
            return buf;
        } catch (Exception e) {
            return new byte[]{};
        }
    }


    /**
     * 读取上一段落
     *
     * @param curBeginPos 当前页起始位置指针
     * @return
     */
    private byte[] readParagraphBack(int curBeginPos) {
        try {
            byte b0;
            int i = curBeginPos - 1;
            while (i > 0) {
                b0 = mbBuff.get(i);
                if (b0 == 0x0a && i != curBeginPos - 1) {
                    i++;
                    break;
                }
                i--;
            }
            int nParaSize = curBeginPos - i;
            byte[] buf = new byte[nParaSize];
            for (int j = 0; j < nParaSize; j++) {
                buf[j] = mbBuff.get(i + j);
            }
            return buf;
        } catch (Exception e) {
            return new byte[]{};
        }
    }

    public boolean hasNextPage() {
        if (chaptersList != null) {
            return currentChapter < chaptersList.size() || curEndPos < mbBufferLen;
        } else {
            return false;
        }
    }

    public boolean hasPrePage() {
        return currentChapter > 1 || (currentChapter == 1 && curBeginPos > 0);
    }

    /**
     * 跳转下一页
     */
    public BookStatus nextPage() {
        if (!hasNextPage()) { // 最后一章的结束页
            return BookStatus.NO_NEXT_PAGE;
        } else {
            tempcurrPage = currentPage;
            tempChapter = currentChapter;
            tempBeginPos = curBeginPos;
            if (curEndPos >= mbBufferLen) { // 中间章节结束页
                currentChapter++;
                int ret = openBook(currentChapter, new int[]{0, 0},true); // 打开下一章
                if (ret == 0) {
                    onLoadChapterFailure(currentChapter);
                    currentChapter--;
                    return BookStatus.NEXT_CHAPTER_LOAD_FAILURE;
                } else {
                    currentPage = 0;
                    onChapterChanged(currentChapter);
                }
            }
            mLines.clear();
            curBeginPos = curEndPos; // 起始指针移到结束位置
            mLines = pageDown(); // 读取一页内容
            onPageChanged(currentChapter, ++currentPage);
        }
        return BookStatus.LOAD_SUCCESS;
    }

    /**
     * 跳转上一页
     */
    public BookStatus prePage() {
        if (!hasPrePage()) { // 第一章第一页
            return BookStatus.NO_PRE_PAGE;
        } else {
            // 保存当前页的值
            tempcurrPage = currentPage;
            tempChapter = currentChapter;
            tempBeginPos = curBeginPos;
            if (curBeginPos <= 0) {
                currentChapter--;
                int ret = openBook(currentChapter, new int[]{0, 0},false);
                if (ret == 0) {
                    onLoadChapterFailure(currentChapter);
                    currentChapter++;
                    return BookStatus.PRE_CHAPTER_LOAD_FAILURE;
                } else { // 跳转到上一章的最后一页
                    mLines.clear();
                    mLines = pageLast();
                    onChapterChanged(currentChapter);
                    onPageChanged(currentChapter, currentPage);
                    return BookStatus.LOAD_SUCCESS;
                }
            }
            mLines.clear();
            pageUp(); // 起始指针移到上一页开始处
            mLines = pageDown(); // 读取一页内容
            onPageChanged(currentChapter, --currentPage);
        }
        return BookStatus.LOAD_SUCCESS;
    }

    public synchronized void cancelPage() {
        currentChapter = tempChapter;
        curBeginPos = tempBeginPos;
//        Log.d("cancelPage", curBeginPos + "");
        curEndPos = curBeginPos;
        currentPage = tempcurrPage;
        if (listener != null) {
            if (capterPageNum != null&&capterPageNum.containsKey(currentChapter)) {
                allPageForChapter = capterPageNum.get(currentChapter);
                listener.onPageNum(allPageForChapter);
            }
            onPageChanged(currentChapter,currentPage);
        }

        int ret = openBook(currentChapter, new int[]{curBeginPos, curEndPos},false);
        if (ret == 0) {
            onLoadChapterFailure(currentChapter);
            return;
        }
        mLines.clear();
        mLines = pageDown();
    }

    /**
     * 获取当前阅读位置
     *
     * @return index 0：起始位置 1：结束位置
     */
    public int[] getPosition() {
        return new int[]{currentChapter, curBeginPos, curEndPos};
    }

    public String getHeadLineStr() {
        if (mLines != null && mLines.size() > 1) {
            return mLines.get(0);
        }
        return "";
    }

    /**
     * 设置字体大小
     *
     * @param fontsize 单位：px
     */
    public void setTextFont(int fontsize,int titleFontsize) {
        mFontSize = fontsize;
        mLineSpace = (int) (mFontSize*mLineMultiple);
        mPartSpace = (int) (PART_SPACE_MULTIPLE * mFontSize);
        mTitleSize = titleFontsize;
        mTitlePaint.setTextSize(mTitleSize);
        mPaint.setTextSize(mFontSize);
        openBook(currentChapter,new int[]{curBeginPos,curEndPos},true);
    }


    /**
     * 设置行间距
     * @param space
     */
    public void setLineSpace(float space) {
        mLineMultiple = space;
        mLineSpace = (int) (mLineMultiple * mFontSize);
        openBook(currentChapter,new int[]{curBeginPos,curEndPos},true);
    }

    /**
     * 根据百分比，跳到目标位置
     *
     * @param persent
     */
    public void setPercent(int persent) {
        float a = (float) (mbBufferLen * persent) / 100;
        curEndPos = (int) a;
        if (curEndPos == 0) {
            nextPage();
        } else {
            nextPage();
            prePage();
            nextPage();
        }
    }

    /**
     * 获取左上角的状态
     */
    private String getTopLeftString() {
        StringBuilder sb = new StringBuilder();
        sb.append(title);
        if (chaptersList != null && chaptersList.size() > 0) {
            sb.append("(").append(currentChapter).append("/").append(chaptersList.size()).append("章)");
        }
        return sb.toString();
    }


    private String getBottomRightString() {
        StringBuilder sb = new StringBuilder();
        sb.append(currentPage).append("/").append(currChapterPageNum);
        if (chaptersList != null && chaptersList.size() > 0) {
            double progress = currentChapter/((double)chaptersList.size())*100;
            sb.append("   ").append(formatDouble(progress)).append("%");
        }
        return sb.toString();
    }

    public static String formatDouble(double progress) {
        DecimalFormat df = new DecimalFormat("###.00");
        String str = df.format(progress);
        if(str.endsWith(".00")){
            return str.replace(".00","");
        }else if(str.endsWith("0")){
            return str.substring(0,str.length()-1);
        }else if(str.startsWith(".")){
            return "0"+str;
        }
        return str;
    }



    public void setOnReadStateChangeListener(OnReadStateChangeListener listener) {
        this.listener = listener;
    }

    void onChapterChanged(int chapter) {
        if (listener != null)
            listener.onChapterChanged(chapter);
    }

    private void onPageChanged(int chapter,int page) {
        if (listener != null) {
            listener.onPageChanged(chapter,page,curBeginPos);
        }
    }

    void onLoadChapterFailure(int chapter) {
        if (listener != null)
            listener.onLoadChapterFailure(chapter);
    }


    public void setFontSize(int fontSize) {
        int titleFontSize = getTitleFontSize(fontSize);
        //重新绘制
        setTextFont(fontSize,titleFontSize);
    }



    public static int getTitleFontSize(int fontSize) {
        return DensityUtil.sp2px(WeMediaApplication.applicationContext, 5)+fontSize;// 计算当前字符大小(px)（粗略）;
    }


    public void setReadTheme(ReadTheme readTheme) {
        mPaint.setColor(mContext.getResources().getColor(readTheme.getContentFontColor()));
        mTitlePaint.setColor(mContext.getResources().getColor(readTheme.getTitleFontColor()));
        mStatusBarPaint.setColor(mContext.getResources().getColor(readTheme.getStatusBarFontColor()));
        mBottomStatusPaint.setColor(mContext.getResources().getColor(readTheme.getStatusBarFontColor()));
        mProgressPaint.setColor(mContext.getResources().getColor(readTheme.getAutoPlayTheme().getTopProgressBgColor()));
    }

    private String title;
    public synchronized void setTitleText(String title) {
        this.title = title;
    }



    private String getTime() {
        if(mobileState == null)
            return "";
        return mobileState.systemTime;
    }



    /**
     * 更新手机状态
     * @param mobileState
     */
    public void upDateMobileState(MobileState mobileState) {
        this.mobileState = mobileState;

    }
}
